﻿using ChholCmdPort;
using Sl.Duplex;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;

namespace ChholConfig.UserSerial {
	/// <summary>
	/// 由CC9D分裂出来的双工收发端口，用于一对多情况下原生串口的收发操作。
	/// </summary>
	public class DuplexCc9d : IDuplex {
		public override string Name => $"远程端口{Remote_addr:X4}.{Remote_port}";
		bool is_running = true;
		public override bool IsRunning => is_running;

		public readonly ushort Remote_addr;
		public readonly byte Remote_port;
		public readonly Action<Pkg> sendData;

		public DuplexCc9d(ushort remote_addr, byte remote_port, Action<Pkg> sendData) {
			Remote_addr = remote_addr;
			Remote_port = remote_port;
			this.sendData = sendData;
		}


		bool is_disposed = false;
		protected override void Dispose(bool disposing) {
			base.Dispose(disposing);
			if (disposing) {
				if (false == is_disposed) {
					is_disposed = true;
					closePort();
				}
			}
		}
		public override void openPort() {
			if (IsRunning) {
				return;
			}
			is_running =  true;
			onPortStatusChange();
		}
		public override  void closePort() {
			if (IsRunning) {
				is_running = false;
				onPortStatusChange();
			}
		}
		private void Sp_ErrorReceived(object sender, SerialErrorReceivedEventArgs e) {
			//closePort();
		}
		private void dataReceived(object sender, SerialDataReceivedEventArgs e) {
			dDataToRead?.Invoke(this);
		}
		public void recvCc9dPkg(Pkg pkg) {
			if (RecvOneByte!=null) {
				for (int i = 0; i < pkg.Data_len; i++) {
					RecvOneByte(this,pkg[i]);
				}
			} else if(RecvMutBytes != null) {
				byte[] data = new byte[pkg.Data_len];
				for (int i = 0; i < pkg.Data_len; i++) {
					data[i] = pkg[i];
				}
				RecvMutBytes(this, data,0, pkg.Data_len);
			} else {
				for (int i = 0; i < pkg.Data_len; i++) {
					readBuf.Enqueue(pkg[i]);
				}
				dDataToRead?.Invoke(this);
			}
		}

		Queue<byte> readBuf = new Queue<byte>(4096);
		Queue<byte> writeBuf = new Queue<byte>(4096);

		public override int Read(byte[] data, int offset, int count) {
			int take_num = 0;
			while (take_num < count) {
				if (readBuf.Count == 0) {
					break;
				}
				var temp = readBuf.Dequeue();
				data[take_num+offset] = temp;
				take_num++;
			}
			Read_count += take_num;
			return take_num;
		}
		public override void Write(byte[] data, int offset, int count) {
			Write_count += count;
			Pkg p = new Pkg();
			p.To_port = Remote_port;
			p.Remote_addr = Remote_addr;
			for (int i = 0; i < count; i++) {
				p[i] = data[offset+i];
			}
			p.Data_len = count;
			sendData(p);
		}
		public override void WriteByte(byte value) {
			throw new NotImplementedException();
			//Write_count ++;
			//sp.BaseStream.WriteByte(value);
		}
		public override int ReadByte() {
			if (readBuf.Count == 0) {
				return -1;
			}
			var temp = readBuf.Dequeue();
			Read_count++;
			return temp;
		}

		public override string config(string str) {
			throw new NotImplementedException();
		}
	}
}
